<?php

namespace Kangcg\WeChat;

use Kangcg\Application\Base\Event;
use Kangcg\WeChat\Library\Component\Appid;
use Kangcg\WeChat\Library\Component\OpenApi;
use Kangcg\WeChat\Library\Urls;
use Kangcg\WeChat\Library\WeChat\Comment;
use Kangcg\WeChat\Library\WeChat\Draft;
use Kangcg\WeChat\Library\WeChat\Media;
use Kangcg\WeChat\Library\WeChat\Menu;
use Kangcg\WeChat\Library\WeChat\MessageFK;
use Kangcg\WeChat\Library\WeChat\MessageMass;
use Kangcg\WeChat\Library\WeChat\MessageServer;
use Kangcg\WeChat\Library\WeChat\MessageTemplate;
use Kangcg\WeChat\Library\WeChat\Ocr;
use Kangcg\WeChat\Library\WeChat\Qrcode;
use Kangcg\WeChat\Library\WeChat\Tag;
use Kangcg\WeChat\Library\WeChat\User;
use Kangcg\WeChat\Library\WeChatTrait;

/**
 * 开放平台--微信
 * $wechat = new Platform(['component_appid' => 'wx5a3bb8ff705081ef', 'component_appsecret' => 'cf3ead3ae67393e54ca0d02beda0967b']);
 * Class Platform
 * @property string $component_appid  第三方平台的appid
 * @property string $component_appsecret  第三方平台的appsecret
 * @property string $component_verify_ticket  第三方平台的component_verify_ticket票据
 * @property string $component_token  第三方平台的消息校验Token
 * @property string $component_encodingAESKey  第三方平台的消息加密密匙
 * @property string $component_access_token  第三方平台的AccessToken
 * @property string $authorizer_appid 授权方 appid
 * @property string $authorizer_access_token 授权方令牌
 * @property string $authorizer_refresh_token 授权方的刷新令牌
 * @package Kang\Libs\WeChat
 */
class WeChatPlatform extends WeChatTrait
{
    use Appid;
    use Comment;
    use Draft;
    use Media;
    use Menu;
    use MessageFK;
    use MessageMass;
    use MessageServer;
    use MessageTemplate;
    use Ocr;
    use OpenApi;
    use Qrcode;
    use Tag;
    use User;

    //授权事件类型
    const AUTHOR_INFO_TYPE_COMPONENT_VERIFY_TICKET = 'component_verify_ticket';
    const AUTHOR_INFO_TYPE_AUTHORIZED = 'authorized'; //授权成功通知
    const AUTHOR_INFO_TYPE_UNAUTHORIZED = 'unauthorized'; //取消授权通知
    const AUTHOR_INFO_TYPE_UPDATEAUTHORIZED = 'updateauthorized'; //授权更新通知

    /**
     * 启动票据推送服务
     * @return bool
     */
    public function startPushTicket()
    {
        $data['component_appid'] = $this->component_appid;
        $data['component_secret'] = $this->component_appsecret;
        if (!$this->httpPost(Urls::COMPONENT_START_PUSH_TICKET, $data)) {
            return false;
        }

        return true;
    }

    /**
     *获取AccessToken
     * @return mixed
     */
    public function getAccessToken()
    {
        if (!$this->authorizer_access_token) {
            $this->authorizer_access_token = $this->refreshAccessToken();
        }

        return $this->authorizer_access_token;
    }

    /**
     * 获取平台方的AccessToken
     * @param string $url
     * @return bool|mixed|string
     */
    public function getComponentAccessToken($url = '')
    {
        if (!$this->component_access_token && !($this->component_access_token = $this->refreshComponentAccessToken())) {
            return false;
        }

        return $url ? ($url . $this->component_access_token) : $this->component_access_token;
    }

    /**
     *刷新AccessToken
     * @return bool|array ['authorizer_access_token' => '授权方令牌', 'expires_in' => '有效期，单位：秒', 'authorizer_refresh_token' => '刷新令牌']
     */
    public function refreshAccessToken()
    {
        $event = new Event();
        $event->sender = $this;
        $this->trigger(self::EVENT_BEFORE_REFRESH_AUTHORIZER_ACCESS_TOKEN, $event);
        if ($event->handled === true) {
            return $event->data['authorizer_access_token'] ?? $event->data;
        }

        $data['component_appid'] = $this->component_appid;
        $data['authorizer_appid'] = $this->authorizer_appid;
        $data['authorizer_refresh_token'] = $this->authorizer_refresh_token;
        if (!$result = $this->httpPost(Urls::APPID_TOKEN_URL, $data, $this->useComponentAccessToken())) {
            return false;
        }

        $event->data = $result;
        $this->trigger(self::EVENT_AFTER_REFRESH_AUTHORIZER_ACCESS_TOKEN, $event);
        return $result;
    }

    /**
     * 获取第三方平台令牌
     * @return bool|string component_access_token
     */
    public function refreshComponentAccessToken()
    {
        $event = new Event();
        $event->sender = $this;
        $this->trigger(self::EVENT_BEFORE_REFRESH_COMPONENT_TOKEN, $event);
        if ($event->handled === true) {
            return $event->data['component_access_token'] ?? $event->data;
        }

        $data['component_appid'] = $this->component_appid;
        $data['component_appsecret'] = $this->component_appsecret;
        $data['component_verify_ticket'] = $this->component_verify_ticket;
        if (!$result = $this->httpPost(Urls::COMPONENT_TOKEN_URL, $data)) {
            return false;
        }

        $event->data = $result;
        $this->trigger(self::EVENT_AFTER_REFRESH_COMPONENT_TOKEN, $event);
        return $result['component_access_token'];
    }

    /**
     * 获取公众的缓存key
     * @return string
     */
    public function getAccessTokenCacheKey()
    {
        return $this->authorizer_appid . $this->authorizer_refresh_token;
    }

    public function getAppid()
    {
        return $this->authorizer_appid;
    }

    private function useComponentAccessToken()
    {
        return $this->_isUseComponentAccessToken = true;
    }

    protected function parseToken($url)
    {
        $token = $this->_isUseComponentAccessToken ? $this->getComponentAccessToken() : $this->getAccessToken();
        $this->_isUseComponentAccessToken = false;
        return $token;
    }

    private $_isUseComponentAccessToken = false;
}
